#ifndef __M_LOG_H__
#define __M_LOG_H__

// 引入相关头文件
#include "util.hpp"
#include "level.hpp"
#include "message.hpp"
#include "formatter.hpp"
#include "sink.hpp"
#include "looper.hpp"
#include <vector>
#include <list>
#include <atomic>
#include <unordered_map>
#include <cstdarg>
#include <type_traits>

// 定义命名空间 bitlog 防止命名冲突
namespace bitlog{

// 前置声明同步和异步日志器类
class SyncLogger;
class AsyncLogger;

// Logger 基类，定义了日志系统的基本接口
class Logger {
    public:
        // 日志器类型：同步或异步
        enum class Type {
            LOGGER_SYNC = 0,   // 同步日志器
            LOGGER_ASYNC       // 异步日志器
        };

        // 智能指针类型定义，便于管理 Logger 对象的生命周期
        using ptr = std::shared_ptr<Logger>; 

        // 构造函数，初始化日志器名称、格式化器、输出目标列表和日志级别
        Logger(const std::string &name, 
            Formatter::ptr formatter,
            std::vector<LogSink::ptr> &sinks, 
            LogLevel::value level = LogLevel::value::DEBUG): 
            _name(name),  _level(level), _formatter(formatter),
            _sinks(sinks.begin(), sinks.end()){
        }

        // 返回日志器的名称
        std::string loggerName() { return _name; }

        // 返回当前日志器的日志级别
        LogLevel::value loggerLevel() { return _level; }

        // 用于记录 DEBUG 级别的日志
        void debug(const char *file, size_t line, const char *fmt, ...) {
            if (shouldLog(LogLevel::value::DEBUG) == false) {
                return ;
            }
            va_list al;
            va_start(al, fmt);
            log(LogLevel::value::DEBUG, file, line, fmt, al);
            va_end(al);
        }

        // 用于记录 INFO 级别的日志
        void info(const char *file, size_t line, const char *fmt, ...) {
            if (shouldLog(LogLevel::value::INFO) == false) return ;
            va_list al;
            va_start(al, fmt);
            log(LogLevel::value::INFO, file, line, fmt, al);
            va_end(al);
        }

        // 用于记录 WARN 级别的日志
        void warn(const char *file, size_t line, const char *fmt, ...) {
            if (shouldLog(LogLevel::value::WARN) == false) return ;
            va_list al;
            va_start(al, fmt);
            log(LogLevel::value::WARN, file, line, fmt, al);
            va_end(al);
        }

        // 用于记录 ERROR 级别的日志
        void error(const char *file, size_t line, const char *fmt, ...) {
            if (shouldLog(LogLevel::value::ERROR) == false) return ;
            va_list al;
            va_start(al, fmt);
            log(LogLevel::value::ERROR, file, line, fmt, al);
            va_end(al);
        }

        // 用于记录 FATAL 级别的日志
        void fatal(const char *file, size_t line, const char *fmt, ...) {
            if (shouldLog(LogLevel::value::FATAL) == false) {
                return ;
            }

            va_list al;
            va_start(al, fmt);
            log(LogLevel::value::FATAL, file, line, fmt, al);
            va_end(al);
        }

    public:
        // 日志器构建器类，帮助用户创建和配置日志器
        class Builder {
            public:
                using ptr = std::shared_ptr<Builder>;

                // 构造函数，初始化日志级别和类型
                Builder():_level(LogLevel::value::DEBUG), 
                    _logger_type(Logger::Type::LOGGER_SYNC) {}

                // 设置日志器的名称
                void buildLoggerName(const std::string &name) { _logger_name = name; }

                // 设置日志器的日志级别
                void buildLoggerLevel(LogLevel::value level) { _level = level; }

                // 设置日志器的类型（同步或异步）
                void buildLoggerType(Logger::Type type) { _logger_type = type; }

                // 设置日志器的格式化器，支持通过字符串或 Formatter 对象
                void buildFormatter(const std::string pattern) { _formatter = std::make_shared<Formatter>(pattern); }
                void buildFormatter(const Formatter::ptr &formatter) { _formatter = formatter; }

                // 添加日志输出目标（Sink），支持多种参数类型
                template<typename SinkType, typename ...Args>
                void buildSink(Args &&...args) { 
                    auto sink = SinkFactory::create<SinkType>(std::forward<Args>(args)...);
                    _sinks.push_back(sink); 
                }

                // 构建日志器的虚函数，具体实现由子类提供
                virtual Logger::ptr build() = 0;

            protected:
                Logger::Type _logger_type;          // 日志器类型
                std::string _logger_name;           // 日志器名称
                LogLevel::value _level;             // 日志器日志级别
                Formatter::ptr _formatter;          // 日志格式化器
                std::vector<LogSink::ptr> _sinks;   // 日志输出目标列表
        };

    protected:
        // 判断是否需要记录当前级别的日志
        bool shouldLog(LogLevel::value level) { return level >= _level; }

        // 日志记录函数，格式化日志信息并调用 logIt 方法输出
        void log(LogLevel::value level, const char *file, size_t line, const char *fmt, va_list al) {
            char *buf;
            std::string msg;
            int len = vasprintf(&buf, fmt, al);
            if (len < 0) {
                msg = "格式化日志消息失败！！";
            } else {
                msg.assign(buf, len);
                free(buf);
            }
            // 创建日志消息对象
            LogMsg lm(_name, file, line, std::move(msg), level);
            std::stringstream ss;
            // 使用格式化器将日志消息格式化为字符串
            _formatter->format(ss, lm);
            // 输出日志
            logIt(std::move(ss.str()));
        }

        // 纯虚函数，具体的日志输出逻辑由子类实现
        virtual void logIt(const std::string &msg) = 0;

    protected:
        std::mutex _mutex;                      // 保护日志记录操作的互斥锁
        std::string _name;                      // 日志器名称
        Formatter::ptr _formatter;              // 日志格式化器
        std::atomic<LogLevel::value> _level;    // 日志级别（原子操作，支持并发）
        std::vector<LogSink::ptr> _sinks;       // 日志输出目标列表
};

// 同步日志器类，继承自 Logger，实现同步日志记录
class SyncLogger : public Logger {
    public:
        using ptr = std::shared_ptr<SyncLogger>;

        // 构造函数，初始化同步日志器
        SyncLogger(const std::string &name, 
            Formatter::ptr formatter,
            std::vector<LogSink::ptr> &sinks, 
            LogLevel::value level = LogLevel::value::DEBUG): 
            Logger(name, formatter, sinks, level){ 
            std::cout << LogLevel::toString(level) << " 同步日志器: " << name << "创建成功...\n";
        }

    private:
        // 实现同步日志输出
        virtual void logIt(const std::string &msg) {
            std::unique_lock<std::mutex> lock(_mutex);
            if (_sinks.empty()) { return ; }
            for (auto &it : _sinks) {
                it->log(msg.c_str(), msg.size());
            }
        }
};

// 异步日志器类，继承自 Logger，实现异步日志记录
class AsyncLogger : public Logger {
    public:
        using ptr = std::shared_ptr<AsyncLogger>;

        // 构造函数，初始化异步日志器和异步循环器
        AsyncLogger(const std::string &name, 
            Formatter::ptr formatter, 
            std::vector<LogSink::ptr> &sinks, 
            LogLevel::value level = LogLevel::value::DEBUG): 
            Logger(name, formatter, sinks, level),
            _looper(std::make_shared<AsyncLooper>(std::bind(&AsyncLogger::backendLogIt, this, std::placeholders::_1))) {
            std::cout << LogLevel::toString(level) << "异步日志器: " << name << "创建成功...\n";
        }

    protected:
        // 将日志消息推送到异步循环器中
        virtual void logIt(const std::string &msg) {
            _looper->push(msg);
        }

        // 在后台线程中处理日志消息并输出
        void backendLogIt(Buffer &msg) {
            if (_sinks.empty()) { 
                return; 
            }
            
            for (auto &it : _sinks) {
                it->log(msg.begin(), msg.readAbleSize());
            }
        }

    protected:
        AsyncLooper::ptr _looper;  // 异步循环器，用于管理异步日志消息的处理
};

// 本地日志器构建器类，继承自 Logger::Builder，用于构建本地日志器
class LocalLoggerBuilder: public Logger::Builder {
    public:
        // 构建日志器对象，如果配置不完整则使用默认配置
        virtual Logger::ptr build() {
            if (_logger_name.empty()) {
                std::cout << "日志器名称不能为空！！";
                abort();  // 如果日志器名称为空，终止程序
            }
            if (_formatter.get() == nullptr) {
                std::cout << "当前日志器：" << _logger_name << " 未检测到日志格式，默认设置为[ %d{%H:%M:%S}%T%t%T[%p]%T[%c]%T%f:%l%T%m%n ]!\n";
                _formatter = std::make_shared<Formatter>();  // 设置默认格式化器
            }
            if (_sinks.empty()) {
                std::cout << "当前日志器：" << _logger_name << " 未检测到落地方向，默认设置为标准输出!\n";
                _sinks.push_back(std::make_shared<StdoutSink>());  // 设置默认输出到标准输出
            }
            Logger::ptr lp;
            if (_logger_type == Logger::Type::LOGGER_ASYNC) {
                lp = std::make_shared<AsyncLogger>(_logger_name, _formatter, _sinks, _level);  // 构建异步日志器
            } else {
                lp = std::make_shared<SyncLogger>(_logger_name, _formatter, _sinks, _level);  // 构建同步日志器
            }
            return lp;
        }
};

// 日志管理器类，单例模式，用于管理系统中的所有日志器
class loggerManager{
    private:
        std::mutex _mutex;  // 互斥锁，保护日志器的添加和查找操作
        Logger::ptr _root_logger;  // 根日志器，系统默认的日志器
        std::unordered_map<std::string, Logger::ptr> _loggers;  // 存储所有日志器的映射表

    private:
        // 私有构造函数，初始化根日志器
        loggerManager(){ 
            std::unique_ptr<LocalLoggerBuilder> slb(new LocalLoggerBuilder());
            slb->buildLoggerName("root");
            slb->buildLoggerType(Logger::Type::LOGGER_SYNC);
            _root_logger = slb->build();
            _loggers.insert(std::make_pair("root", _root_logger));
        }

        // 禁止拷贝构造和赋值操作
        loggerManager(const loggerManager&) = delete;
        loggerManager &operator=(const loggerManager&) = delete;

    public:
        // 获取日志管理器实例（单例模式）
        static loggerManager& getInstance() {
            static loggerManager lm;
            return lm;
        }

        // 检查是否已经存在指定名称的日志器
        bool hasLogger(const std::string &name)  {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _loggers.find(name);
            return it != _loggers.end();
        }

        // 添加新的日志器
        void addLogger(const std::string &name, const Logger::ptr logger) {
            std::unique_lock<std::mutex> lock(_mutex);
            _loggers.insert(std::make_pair(name, logger));
        }

        // 获取指定名称的日志器
        Logger::ptr getLogger(const std::string &name) {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _loggers.find(name);
            if (it == _loggers.end()) {
                return Logger::ptr();
            }
            return it->second;
        }

        // 获取根日志器
        Logger::ptr rootLogger() {
            std::unique_lock<std::mutex> lock(_mutex);
            return _root_logger;
        }
};


/*
    static int num = 1;
    std::string logger_name = "async_bench_logger" + std::to_string(num++);
    LOGI("************************************************");
    LOGI("异步日志测试: %d threads, %d messages", thread_count, msg_count);

    bitlog::GlobalLoggerBuilder::ptr lbp(new bitlog::GlobalLoggerBuilder);
    lbp->buildLoggerName(logger_name);
    lbp->buildFormatter("%m");
    lbp->buildSink<bitlog::FileSink>("./logs/async.log");
    lbp->buildLoggerType(bitlog::Logger::Type::LOGGER_ASYNC);
    lbp->build(); 
    bitlog::bench(logger_name, thread_count, msglen, msg_count);
*/


// 全局日志器构建器类，继承自 Logger::Builder，用于构建全局日志器
class GlobalLoggerBuilder: public Logger::Builder {
    public:
        // 构建日志器对象，如果配置不完整则使用默认配置
        virtual Logger::ptr build() {
            if (_logger_name.empty()) {
                std::cout << "日志器名称不能为空！！";
                abort();  // 如果日志器名称为空，终止程序
            }
            //创建出来全局唯一的 loggerManager 对象
            assert(loggerManager::getInstance().hasLogger(_logger_name) == false);  // 确保日志器名称唯一
            if (_formatter.get() == nullptr) {
                std::cout << "当前日志器：" << _logger_name << " 未检测到日志格式，默认设置为[ %d{%H:%M:%S}%T%t%T[%p]%T[%c]%T%f:%l%T%m%n ]!\n";
                _formatter = std::make_shared<Formatter>();  // 设置默认格式化器
            }
            if (_sinks.empty()) {
                std::cout << "当前日志器：" << _logger_name << " 未检测到落地方向，默认设置为标准输出!\n";
                _sinks.push_back(std::make_shared<StdoutSink>());  // 设置默认输出到标准输出
            }
            Logger::ptr lp;
            if (_logger_type == Logger::Type::LOGGER_ASYNC) {
                lp = std::make_shared<AsyncLogger>(_logger_name, _formatter, _sinks, _level);  // 构建异步日志器
            } else {
                lp = std::make_shared<SyncLogger>(_logger_name, _formatter, _sinks, _level);  // 构建同步日志器
            }
            //// 将构建好的日志器添加到日志管理器中
            loggerManager::getInstance().addLogger(_logger_name, lp);  
            return lp;
        }
};

} // 命名空间 bitlog 结束

#endif // __M_LOG_H__ 结束
